﻿#region Copyright (c) 2000-2008 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{       AgDataGrid                                 }
{                                                                   }
{       Copyright (c) 2000-2008 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2008 Developer Express Inc.

using System;
using System.Collections.Generic;
using DevExpress.AgDataGrid.Data.Helpers;
namespace DevExpress.AgDataGrid.Data {
	public class NullDictionary {
		Dictionary<object, object> dictionary;
		public NullDictionary() {
			this.dictionary = new Dictionary<object, object>();
		}
		protected bool ContainsNullKey { get; set; }
		protected Dictionary<object, object> Dictionary { get { return dictionary; } }
		protected object NullKeyValue { get; set; }
		public void Add(object key, object value) {
			if (key != null) {
				if(!Dictionary.ContainsKey(key)) {
					Dictionary.Add(key, value);
				}
			} else {
				ContainsNullKey = true;
				NullKeyValue = value;
			}
		}
		public void Clear() {
			Dictionary.Clear();
			ContainsNullKey = false;
		}
		public bool ContainsKey(object key) {
			return (key != null) ? Dictionary.ContainsKey(key) : ContainsNullKey;
		}
		public object Get(object key) {
			return (key != null) ? Dictionary[key] : NullKeyValue;
		}
	}
	public abstract class GroupRowsHastableSaveRestoreBase {
		DataController controller;
		NullDictionary rootHashtable;
		int restoredGroupCount;
		public GroupRowsHastableSaveRestoreBase(DataController controller, NullDictionary rootHashtable, int restoredGroupCount) {
			this.controller = controller;
			this.rootHashtable = rootHashtable;
			this.restoredGroupCount = restoredGroupCount;
		}
		protected DataController Controller { get { return controller; } }
		protected NullDictionary RootHashtable { get { return rootHashtable; } }
		protected int RestoredGroupCount { get { return restoredGroupCount; } }
		public virtual void Perform() {
			NullDictionary prevHashtable = null;
			GroupRowInfo prevRowInfo = null;
			for (int i = 0; i < Controller.GroupInfo.Count; i++) {
				GroupRowInfo row = Controller.GroupInfo[i];
				if (!CanPerformRow(row)) continue; 
				NullDictionary hashtable = GetHashtable(row, prevRowInfo, prevHashtable);
				if (hashtable != null) {
					OnRowSaveRestore(hashtable, row);
				}
				prevRowInfo = row;
				prevHashtable = hashtable;
			}
		}
		protected abstract void OnRowSaveRestore(NullDictionary hashtable, GroupRowInfo row);
		protected virtual bool CanPerformRow(GroupRowInfo row) { return row.Level < RestoredGroupCount; }
		protected object GetRowValue(GroupRowInfo row) {
			DataColumn column = Controller.SortInfo[row.Level].Column;
			return Controller.GetRowValue(row.ChildControllerRow, column);
		}
		NullDictionary GetHashtable(GroupRowInfo row, GroupRowInfo prevRow, NullDictionary prevHashtable) {
			if (row.ParentGroup == null) return RootHashtable;
			if (prevRow == null) return null;
			if (prevRow.ParentGroup == row.ParentGroup) return prevHashtable;
			if (prevRow == row.ParentGroup) {
				object keyValue = GetRowValue(row.ParentGroup);
				if(prevHashtable == null) return null;
				if(prevHashtable.ContainsKey(keyValue)) {
					return prevHashtable.Get(keyValue) as NullDictionary;
				}
			}
			return null;
		}
	}
	public class GroupRowsHastableSave : GroupRowsHastableSaveRestoreBase {
		public GroupRowsHastableSave(DataController controller, NullDictionary rootHashtable, int restoredGroupCount)
			: base(controller, rootHashtable, restoredGroupCount) {
		}
		public override void Perform() {
			RootHashtable.Clear();
			base.Perform();
		}
		protected override void OnRowSaveRestore(NullDictionary hashtable, GroupRowInfo row) {
			 hashtable.Add(GetRowValue(row), row.Level < RestoredGroupCount - 1 ? new NullDictionary() : null);
		}
		protected override bool  CanPerformRow(GroupRowInfo row) {  return base.CanPerformRow(row) && row.Expanded; }
	}
	public class GroupRowsHastableRestore : GroupRowsHastableSaveRestoreBase {
		public GroupRowsHastableRestore(DataController controller, NullDictionary rootHashtable, int restoredGroupCount)
			: base(controller, rootHashtable, restoredGroupCount) {
		}
		protected override void OnRowSaveRestore(NullDictionary hashtable, GroupRowInfo row) {
			row.Expanded = hashtable.ContainsKey(GetRowValue(row));
		}
	}
	public class GroupRowsKeeper {
		DataController controller;
		List<DataColumn> savedGroupColumns;
		NullDictionary rootHashtable;
		public GroupRowsKeeper(DataController controller) {
			this.controller = controller;
			this.savedGroupColumns = new List<DataColumn>();
			this.rootHashtable = new NullDictionary();
		}
		protected DataController Controller { get { return controller; } }
		protected int CurrentGroupCount { get { return Controller.SortInfo.GroupCount; } }
		protected int SavedGroupCount { get { return savedGroupColumns.Count; } }
		protected List<DataColumn> SavedGroupColumns { get { return savedGroupColumns; } }
		protected NullDictionary RootHashtable { get { return rootHashtable; } }
		public bool CanRestore() {
			return GetCanRestoreGroupCount() > 0;
		}
		public void SaveGroupsState() {
			if (!CanRestore()) return;
			new GroupRowsHastableSave(Controller, RootHashtable, GetCanRestoreGroupCount()).Perform();
		}
		public void RestoreGroupsState() {
			if (CanRestore()) {
				new GroupRowsHastableRestore(Controller, RootHashtable, GetCanRestoreGroupCount()).Perform();
			}
			SaveGroupedColumns();
		}
		protected internal void SaveGroupedColumns() {
			SavedGroupColumns.Clear();
			for (int i = 0; i < CurrentGroupCount; i++) {
				SavedGroupColumns.Add(Controller.SortInfo[i].Column);
			}
		}
		protected int GetCanRestoreGroupCount() {
			int count = 0;
			for (int i = 0; i < Math.Min(SavedGroupCount, CurrentGroupCount); i++) {
				if (SavedGroupColumns[i] != Controller.SortInfo[i].Column) break;
				count++;
			}
			return count;
		}
	}
}
